package com.outstanding.his.entity.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.outstanding.his.entity.dao.IEntityDao;
import com.outstanding.his.util.pager.Pagination;

/**
 * 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类.
 * <p/>
 * 子类只要在类定义时指定所管理Entity的Class, 即拥有对单个Entity对象的CRUD操作.
 * 
 * <pre>
 * public class UserManager extends HibernateEntityDao&lt;User&gt; {
 * }
 * </pre>
 * 
 * @param <T>
 * 
 * @see HibernateGenericDao
 */

public class HibernateEntityDao<T> extends HibernateDaoSupport implements
		IEntityDao<T> {

	protected String entityClass;// DAO所管理的Entity类型.

	@SuppressWarnings("unchecked")
	protected Class getEntityClass() {
		Class clazz = null;
		try {
			clazz = Class.forName(entityClass);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return clazz;
	}

	public void setEntityClass(String entityClass) {
		this.entityClass = entityClass;
	}

	public Object getEntity(Serializable entityId) {
		return getHibernateTemplate().load(getEntityClass(), entityId);
	}

	@SuppressWarnings("unchecked")
	public Integer getEntityCount() {
		List<T> count = getHibernateTemplate().find(
				"select count(*) from " + entityClass);
		return ((Long) count.get(0)).intValue();
	}

	private Query createQuery(String hql, Object[] parameters) {
		Query query = getSession().createQuery(hql);
		if (parameters == null)
			return query;
		for (int i = 0; i < parameters.length; i++) {
			query.setParameter(i, parameters[i]);
		}
		return query;
	}

	/**
	 * 分页查询函数，使用hql.
	 * 
	 * @param pageNo
	 *            页号,从1开始.
	 */
	public Pagination pagedEntityQuery(String hql, int pageNo, int pageSize,
			Object[] parameters) {
		return this.pagedEntityQuery(hql, pageNo, pageSize, 1, parameters);
	}

	@SuppressWarnings("unchecked")
	public Pagination pagedEntityQuery(String hql, int pageNo, int pageSize,
			int pageSpan, Object[] parameters) {
		// Count查询
		String countQueryString = " select count (*) "
				+ removeSelect(removeOrders(hql));
		List<T> countlist = getHibernateTemplate().find(countQueryString,
				parameters);
		int totalCount = ((Long) countlist.get(0)).intValue();

		if (totalCount < 1)
			return new Pagination();
		// 实际查询返回分页对象
		int firstIndex = Pagination.getFirstIndex(pageNo, pageSize);
		Query query = createQuery(hql, parameters);
		List list = query.setFirstResult(firstIndex).setMaxResults(
				pageSize * pageSpan).list();
		return new Pagination(firstIndex, totalCount, pageSize, list);
	}

	@SuppressWarnings("unchecked")
	public List<T> listEntity(final String hql, final int firstIndex,
			final int pageSize, final Object[] parameters) {

		List<T> list = getHibernateTemplate().executeFind(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						if (parameters != null) {
							for (int i = 0; i < parameters.length; i++) {
								query.setParameter(i, parameters[i]);
							}
						}
						// Projections.rowCount();
						query.setFirstResult(firstIndex);
						query.setMaxResults(pageSize);
						return query.list();
					}
				});
		return list;
	}

	public void saveEntity(Object object) {
		getHibernateTemplate().saveOrUpdate(object);
	}

	@SuppressWarnings("unchecked")
	public List<T> listAllEntity() {
		return getHibernateTemplate().find("from " + entityClass);
	}

	public void removeEntity(Object object) {
		getHibernateTemplate().delete(object);
	}

	@Override
	public void removeEntityById(Serializable entityId) {
		getHibernateTemplate().delete(getEntity(entityId));
	}

	/**
	 * 去除hql的select 子句，未考虑union的情况,用于pagedQuery.
	 * 
	 * @see #pagedQuery(String,int,int,Object[])
	 */
	private static String removeSelect(String hql) {
		int beginPos = hql.toLowerCase().indexOf("from");
		return hql.substring(beginPos);
	}

	/**
	 * 去除hql的orderby 子句，用于pagedQuery.
	 * 
	 * @see #pagedQuery(String,int,int,Object[])
	 */
	private static String removeOrders(String hql) {
		Pattern pattern = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*",
				Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(hql);
		StringBuffer stringBuffer = new StringBuffer();
		while (matcher.find()) {
			matcher.appendReplacement(stringBuffer, "");
		}
		matcher.appendTail(stringBuffer);
		return stringBuffer.toString();
	}
}
